package mediaCoreLib.managers
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	
	import mediaCoreLib.core.PlaylistObject;
	
	public class PlaylistManager extends EventDispatcher
	{
		///////////////////////////////////////////////////////
		//	STATIC
		///////////////////////////////////////////////////////
		
		static private var _cachedMedia:Object = {}; //storage point for prev downloaded data
		
		///////////////////////////////////////////////////////
		//	CONSOLE
		///////////////////////////////////////////////////////
		
		public function play ():void
		{
			if (!_currentPlaylistObj && mediaQueue[index])
				_currentPlaylistObj = mediaQueue[index];
				
			_currentPlaylistObj.play();
			setIsPlaying(_currentPlaylistObj.isPlaying);
		}
		
		public function pause ():void
		{
			_currentPlaylistObj.pause();
			setIsPlaying(_currentPlaylistObj.isPlaying);
		}
		
		public function stop ():void
		{
			_currentPlaylistObj.stop();
			setIsPlaying(_currentPlaylistObj.isPlaying);
			
			index = 0;
		}
		
		///////////////////////////////////////////////////////
		//	IS PLAYING
		///////////////////////////////////////////////////////
		
		private var _isPlaying:Boolean = false;
		
		[Bindable("isPlayingChanged")]
		public function get isPlaying ():Boolean
		{
			return _isPlaying;
		}
		
		private function setIsPlaying (value:Boolean):void
		{
			_isPlaying = value;
			dispatchEvent(new Event("isPlayingChanged"));
		}
		
		///////////////////////////////////////////////////////
		//	PLAYLIST
		///////////////////////////////////////////////////////
		
		private var _pl:Array = [];
		
		public function get playlist ():Array
		{
			return _pl;
		}
		
		public function set playlist (value:Array):void
		{
			if (_pl.toString() != value.toString())
			{
				_pl = value;
				index = 0;
				
				dispatchEvent(new Event("playlistChanged"));
				
				mediaRetrieved = false;
				getPlaylistMedia(_pl);
			}
		}
		
		///////////////////////////////////////////////////////
		//	DOWNLOAD MEDIA
		///////////////////////////////////////////////////////
		
		private var _currentPlaylistObj:PlaylistObject;
		
		protected var mediaQueue:Array = []; //contains objects PlaylistObjects
		
		protected var mediaRetrieved:Boolean = false;
		
		protected function getPlaylistMedia (urls:Array):void
		{
			mediaQueue = [];
			
			var obj:PlaylistObject;
			var url:String
			for each (url in urls)
			{
				//check to see if media exists in dict if not, retrieve it
				if (_cachedMedia[url] == null)
				{
					obj = new PlaylistObject();
					obj.url = url;
					obj.addEventListener(Event.COMPLETE, onGetMediaComplete);
					obj.addEventListener(IOErrorEvent.IO_ERROR, onGetMediaIOError);
					obj.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);
					
					_cachedMedia[url] = obj;
				}
				
				else
					obj = _cachedMedia[url];
				
				mediaQueue.push(obj);
			}
			
			mediaRetrieved = true;
		}
		
		///////////////////////////////////////////////////////
		//	MISC. EVT HANDLERS
		///////////////////////////////////////////////////////
		
		//these are dispatched from the PlaylistObjects
		protected function onGetMediaComplete (evt:Event):void
		{
			//no issues getting file, so we just do a bit of clean up
			var obj:PlaylistObject = PlaylistObject(evt.target);
			obj.removeEventListener(Event.COMPLETE, onGetMediaComplete);
			obj.removeEventListener(IOErrorEvent.IO_ERROR, onGetMediaIOError);
		}
		
		//these are dispatched from the PlaylistObjects
		protected function onGetMediaIOError (evt:IOErrorEvent):void
		{
			//uh oh we had an issue.  We kick this one out of our media queue and if needed throw an indication
			var obj:PlaylistObject = PlaylistObject(evt.target);
			obj.removeEventListener(Event.COMPLETE, onGetMediaComplete);
			obj.removeEventListener(IOErrorEvent.IO_ERROR, onGetMediaIOError);
			
			mediaQueue[obj.url] = null;
		}
		
		protected function onSoundComplete (evt:Event):void
		{
			//need to advance the index back to the beginning
			if (index == mediaQueue.length - 1)
			{
				stop();
				
				index = 0;
				
				if (allowLoop)
					play();
			}
			
			//we are just going to the next item in the playlist
			else
				index++;
		}
		
		///////////////////////////////////////////////////////
		//	MISC. CONSOLE OPTIONS
		///////////////////////////////////////////////////////
		
		private var _allowLoop:Boolean = false;
		
		[Bindable("allowLoopChanged")]
		public function get allowLoop ():Boolean
		{
			return _allowLoop;
		}
		
		public function set allowLoop (value:Boolean):void
		{
			if (_allowLoop != value)
			{
				_allowLoop = value;
				
				dispatchEvent(new Event("allowLoopChanged"));
			}
		}
		
		///////////////////////////////////////////////////////
		//	INDEX
		///////////////////////////////////////////////////////
		
		private var _index:uint;
		//private var _indexChanged:Boolean = false;
		
		[Bindable("indexChanged")]
		public function get index ():uint
		{
			return _index;
		}
		
		public function set index (value:uint):void
		{
			if (_index != value)
			{
				_index = value;
				
				//check to make sure we are not out of bounds
				if (_index >= mediaQueue.length)
				{
					if (mediaQueue.length == 0)
						_index = 0;
						
					else
						_index = mediaQueue.length - 1;
				}
				
				//check to see if we are playing & all media has been queued for retreival
				if (isPlaying && mediaRetrieved)
				{
					if (_currentPlaylistObj)
						_currentPlaylistObj.stop();
					
					_currentPlaylistObj = mediaQueue[index];
					_currentPlaylistObj.play();
				}
				
				//otherwise we just update the next available obj
				else
					_currentPlaylistObj = mediaQueue[index];
				
				//let others know
				dispatchEvent(new Event("indexChanged"));
			}
		}
		
		///////////////////////////////////////////////////////
		//	SINGLETON
		///////////////////////////////////////////////////////
		
		static private var _instance:PlaylistManager;
		
		static public function getInstance ():PlaylistManager
		{
			if (!_instance)
				_instance = new PlaylistManager();
				
			return _instance;
		}
		
		function PlaylistManager ()
		{
			super();
		}
	}
}